#!/usr/bin/python2
import os
import sys
import errno
import uuid
import subprocess
import time

sys.path.insert(0, os.path.abspath(os.path.split(os.path.realpath(__file__))[0]) + "/../lich/admin/")

from utils import Exp, _exec_pipe, _exec_shell, _get_value
from storage import Storage
from config import Config

tmp_file = '/dev/shm/tmp.xxxx'

class TestObject:
    def __init__(self, bucket, tab = {}):
        self.bucket = bucket
        self.tab = {}
        self.config = Config()
        self.storage = Storage(self.config)

        for (k, v) in tab.items():
            self.tab[k] = v

        retry = 0
        while (1):
            try:
                print("create " + bucket)
                self.storage.create(bucket)
            except Exp, e:
                if (retry > 40):
                    raise
                elif (e.errno == errno.EEXIST):
                    pass
                else:
                    time.sleep(1)
                    retry += 1
                    print ("create %s retry %u", (retry))
                    continue

            break

    def __remove_object(self, obj):
        retry = 0
        while (1):
            try:
                self.storage.remove(obj)
            except Exp, e:
                if (retry > 40):
                    raise Exp(e.errno, "remove fail")
                elif (e.errno == errno.EAGAIN or e.errno == errno.ENONET
                      or e.errno == errno.ENOSYS):
                    time.sleep(1)
                    retry += 1
                    print ("remove retry : %s" % (obj))
                elif (e.errno == errno.ENOENT):
                    break
                else:
                    raise
            else:
                break

    def __clone_object(self, k, v, idx, total, replace = False):
        src = tmp_file
        dist = self.bucket + '/' + k
        #_exec_shell(['echo', obj, '>', src])
        os.system('echo %s > %s' % (v, src))

        print ("clone %s to %s value (%s) (%s/%s)" % (':' + src, dist, v, idx, total))

        retry = 0
        while (1):
            try:
                self.storage.clone(':' + src, dist, replace)
            except Exp, e:
                if (retry > 40):
                    raise Exp(e.errno, "clone fail")
                elif (e.errno == errno.EEXIST):
                    self.__remove_object(dist)
                    continue
                elif (e.errno == errno.EAGAIN or e.errno == errno.ENONET
                      or e.errno == errno.ENOSYS):
                    time.sleep(1)
                    retry += 1
                    print ("clone retry : %s" % (dist))
                else:
                    raise
            else:
                break

        os.system("rm " + src)

    def create(self, tab):
        idx = 0
        for (k, v) in tab.items():
            self.__clone_object(k, v, idx, len(tab))
            idx += 1
            self.tab[k] = v

    def update(self, tab):
        idx = 0
        for (k, v) in tab.items():
            self.__clone_object(k, v, idx, len(tab), True)
            idx += 1
            self.tab[k] = v

    def __check_object(self, k, v, idx, total):
        dist = tmp_file
        src = self.bucket + '/' + k
        os.system("rm -rf " + dist)
        print ("clone %s %s need (%s) (%s/%s)" % (src, ':' + dist, v, idx, total))

        retry = 0
        while (1):
            try:
                self.storage.clone(src, ':' + dist)
            except Exp, e:
                if (retry > 200):
                    raise Exp(e.errno, "clone fail")
                elif (e.errno == errno.EAGAIN or e.errno == errno.ENONET
                      or e.errno == errno.ENOSYS):
                    time.sleep(1)
                    retry += 1
                    os.system("rm -rf " + dist)
                    print ("check retry %u : %s" % (retry, src))
                else:
                    raise
            else:
                break

        buf = _get_value(dist)
        if (buf != v + "\n"):
            raise Exp(errno.EIO, "check object fail")

        #os.system("rm " + dist)

    def check(self):
        idx = 0
        for (k, v) in self.tab.items():
            self.__check_object(k, v, idx, len(self.tab))
            idx += 1



def testobject(count):
    tab = {}
    for i in range(count):
        tab[(str(uuid.uuid1()))] = str(uuid.uuid1())

    bucket = '/pool1/' + str(uuid.uuid1())

    testobject = TestObject(bucket)
    testobject.create(tab)
    testobject.check()

    for (k, v) in tab.items():
        tab[k] = str(uuid.uuid1()) + str(uuid.uuid1())

    testobject.update(tab)
    testobject.check()


if __name__ == '__main__':
    testobject(3)
